

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:ponydata_desk/utils/shared_key.dart';
import '../main.dart';
import 'api.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:bot_toast/bot_toast.dart';

class HttpUtil {

  static String jwt_token="";

  static Dio dio = Dio();

  static void initOptions(){

    dio.options= BaseOptions(
      //请求基地址,可以包含子路径
      baseUrl: Api.BASE_URL,
      //连接服务器超时时间，单位是毫秒.
      connectTimeout: 15000,
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      receiveTimeout: 15000,
      //Http请求头.
      headers:{
        //do something
        "token": jwt_token!=null?jwt_token:""
      },
      //请求的Content-Type，默认值是[ContentType.json]. 也可以用ContentType.parse("application/x-www-form-urlencoded")
      contentType: 'application/json',
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.json,
    );

    dio.interceptors.add(InterceptorsWrapper(
        onRequest:(options, handler){
          // Do something before request is sent
          return handler.next(options); //continue
          // If you want to resolve the request with some custom data，
          // you can resolve a `Response` object eg: `handler.resolve(response)`.
          // If you want to reject the request with a error message,
          // you can reject a `DioError` object eg: `handler.reject(dioError)`
        },
        onResponse:(response,handler) {
          if(response.data['code']=='A0200'){
            clearUserInfo();
            BotToast.closeAllLoading();
            BotToast.showText(text: '登录失效,请重新登录');
            BuildContext context =navigatorKey.currentState!.overlay!.context;
            //关闭drawer
            //Navigator.of(context).pop();
            Navigator.of(context).pushNamedAndRemoveUntil("/login", (route) =>route == null);
            return;
          }
          // Do something with response data
          return handler.next(response); // continue
          // If you want to reject the request with a error message,
          // you can reject a `DioError` object eg: `handler.reject(dioError)`
        },
        onError: (DioError e, handler) {
          // Do something with response error
          return  handler.next(e);//continue
          // If you want to resolve the request with some custom data，
          // you can resolve a `Response` object eg: `handler.resolve(response)`.
        }
    ));
  }

  /*
   * get请求
   */
  static get(url, {data, options, cancelToken}) async {
    late Response response;
    try {
      response = await dio.get(url,
          queryParameters: data, options: options, cancelToken: cancelToken);

    } on DioError catch (e) {
      print('e.response${e}');
      if(e.response!=null){
        // print('code=${e.response.statusCode}');
        return errorResponse(e.response!);
      }
      return {'code':10000,'data':{"msg":e.toString()}};
    }

    return errorResponse(response);

    return {'code':response.statusCode,'data':response.data};
  }
  /*
   * post请求  queryParameters: data,
   */
 static post(url, {data, options, cancelToken}) async {
    Response response;
    try {

      response = await dio.post(url,data: data,
          options: options, cancelToken: cancelToken);
      print('post success---------${response.data}');



    } on DioError catch (e) {
      print('e.response${e}');
      if(e.response!=null){
        return errorResponse(e.response!);

//        return {'code':e.response.statusCode!=null?e.response.statusCode:10000,'data':e.response.data};
      }
      return {'code':10000,'data':{"msg":e.toString()}};
    }

    return errorResponse(response);
  }


  static postToken(url, {data, options, cancelToken}) async {
    Response response;
    try {
      print(jwt_token);
      response = await dio.post(url,data: data,
          options: options,queryParameters:{'token':jwt_token}, cancelToken: cancelToken);
      // print('post success---------${response.headers}');
    } on DioError catch (e) {
      print('e.response${e}');
      if(e.response!=null){
        return errorResponse(e.response!);

//        return {'code':e.response.statusCode!=null?e.response.statusCode:10000,'data':e.response.data};
      }
      return {'code':10000,'data':{"msg":e.toString()}};
    }

    return errorResponse(response);
  }


  put(url, {data, options, cancelToken}) async {
    Response response;
    try {
      response = await dio.put(url,data: data,
          options: options, cancelToken: cancelToken);
      print('post success---------${response.data}');
    } on DioError catch (e) {
      print('e.response${e}');
      if(e.response!=null){
        return errorResponse(e.response!);
      }
      return {'code':10000,'data':{"msg":e.toString()}};
    }
    return {'code':response.statusCode,'data':response.data};
  }

  delete(url, {data, options, cancelToken}) async {
    Response response;
    try {
      response = await dio.delete(url,data: data,
          options: options, cancelToken: cancelToken);
      print('post success---------${response.statusCode}');
    } on DioError catch (e) {
      print('e.response${e}');
      if(e.response!=null){
        return errorResponse(e.response!);
      }
      return {'code':10000,'data':{"msg":e.toString()}};
    }
    if(response is String){
      return {'code':201,'data':"ok"};
    }
    return {'code':response.statusCode,'data':response.data};
  }


  getTwoRequest(url1,url2,{data1,data2,cancelToken})async{
    late List response;
    try {
      response = await Future.wait([dio.get(url1,queryParameters:data1,cancelToken:cancelToken), dio.get(url2,queryParameters:data2,cancelToken: cancelToken)]);

    } on DioError catch (e) {
      if(e.response!=null){
        return errorResponse(e.response!);
      }
      return {'code':10000,'data':e.toString()};    }

    return {'code':200,'data':response};

  }


  static postParam(url, {queryParameters = null, options, cancelToken}) async {
    late Response response;
    try {
      response = await dio.post(url,queryParameters: queryParameters,
          options: options, cancelToken: cancelToken);
      print('post success---------${response.data}');
    } on DioError catch (e) {
      print('post error---------$e');
      formatError(e);
    }
    return response;
  }


  static errorResponse(Response response) async {

    print('url==${response.requestOptions.path}---param:${response.requestOptions.data}--${response.requestOptions.queryParameters}----${response.data}');

    if(response.statusCode=='A0200' || (response.data['err_code'] !=null && response.data['err_code']==100003)){
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.remove(SharedKey.USER_KEY);
      BuildContext context =navigatorKey.currentState!.overlay!.context;
      //关闭drawer
//      Navigator.of(context).pop();
      Navigator.of(context).pushNamedAndRemoveUntil("/login", (route) =>route == null);
      response.data = {"msg":"登录状态失效，请从新登录"};
    }
    return {'code':response.statusCode!=null?response.statusCode:10000,'data':response.data};
  }


  /*
   * 下载文件
   */
  static downloadFile(urlPath, savePath) async {
    late Response response ;
    try {
      response = await dio.download(urlPath, savePath,
          onReceiveProgress: (int count, int total) {
            //进度
            print("$count $total");
          });
      print('downloadFile success---------${response.data}');
    } on DioError catch (e) {
      print('downloadFile error---------$e');
      formatError(e);
    }
    return response.data;
  }

  /*
   * error统一处理
   */
  static void formatError(DioError e) {
    if (e.type == DioErrorType.connectTimeout) {
      // It occurs when url is opened timeout.
      print("连接超时");
    } else if (e.type == DioErrorType.sendTimeout) {
      // It occurs when url is sent timeout.
      print("请求超时");
    } else if (e.type == DioErrorType.receiveTimeout) {
      //It occurs when receiving timeout
      print("响应超时");
    } else if (e.type == DioErrorType.response) {
      // When the server response, but with a incorrect status, such as 404, 503...
      print("出现异常");
    } else if (e.type == DioErrorType.cancel) {
      // When the request is cancelled, dio will throw a error with this type.
      print("请求取消");
    } else {
      //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
      print("未知错误");
    }
  }

  /*
   * 取消请求
   *
   * 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  static void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }

  static void clearUserInfo() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.remove(SharedKey.USER_KEY);
    prefs.remove(SharedKey.GARAGE);
  }

}
